<template>
  <div ref="popoverref" class="inline-block" v-click-away="closepop">
    <!--    内容插槽-->
    <teleport to="body">
      <div v-show="visible" ref="contentref" class="bg-white absolute border p-1 z-20" @click.stop="thisonClick">
        <slot></slot>
        <!--      那个三角形-->
        <div ref="sanjiaoxingref" class="absolute transform block bg-white border-t border-l w-2 h-2 z-10"
             :class="{'-top-1 left-1/2 -translate-x-1/2 rotate-45':thisposition==='bottom',
           '-bottom-1 left-1/2 -translate-x-1/2 -rotate-135':thisposition==='top',
           'top-1/2 -translate-y-1/2 -right-1 rotate-135':thisposition==='left',
           '-left-1 top-1/2 -translate-y-1/2 -rotate-45':thisposition==='right'}"></div>
      </div>
    </teleport>
    <!--    触发插槽-->
    <div class="inline-block" ref="triggerref" @click.stop="thisonClick">
      <slot name="trigger"></slot>
    </div>
  </div>
</template>

<script setup>
import {ref, defineProps, defineEmits, nextTick, onMounted, onBeforeUnmount, useSlots} from "vue"
import {useStore} from "vuex";
import {useRoute, useRouter} from "vue-router";

const slots = useSlots()
const store = useStore()
const route = useRoute()
const router = useRouter()
const prop = defineProps({
  // 触发方式
  trigger: {
    type: String,
    default: "hover",
    // hold的意思是按住鼠标左键不放
    validator(value) {
      return ["hover", "click", "focus", "hold", "default"].includes(value)
    }
  },
  // 定位位置
  position: {
    type: String,
    default: "bottom",
    validator(value) {
      return ["top", "left", "bottom", "right"].includes(value)
    },
  },
  samewidth: {
    type: Boolean,
    default: false,
  },
})
// 定位
const thisposition = ref(prop.position)
// 显示隐藏的状态
const visible = ref(false)
// 三个ref
const popoverref = ref(null)
const contentref = ref(null)
const triggerref = ref(null)

// 最重要的函数，为pop进行定位
const positionContent = () => {
  const {width, height, top, left} = triggerref.value.children[0].getBoundingClientRect()
  let width2, height2
  if (prop.samewidth) {
    contentref.value.style.width = `${width}px`
    width2 = width
    height2 = contentref.value.offsetHeight
  } else {
    width2 = contentref.value.offsetWidth
    height2 = contentref.value.offsetHeight
  }
  let dingwei = {
    top: {
      top: top + window.scrollY - height2 - 5,
      left: left + window.scrollX + width / 2 - width2 / 2
    },
    bottom: {
      top: top + height + window.scrollY + 5,
      left: left + window.scrollX + width / 2 - width2 / 2
    },
    left: {
      top: top + window.scrollY + height / 2 - height2 / 2,
      left: left - width2 + window.scrollX - 7
    },
    right: {
      top: top + window.scrollY + height / 2 - height2 / 2,
      left: left + width + window.scrollX + 7
    },
  }
  contentref.value.style.left = `${dingwei[prop.position].left}px`
  contentref.value.style.top = `${dingwei[prop.position].top}px`
}
// 点击方法
const thisonClick = (e) => {
  if (prop.trigger === "click") {
    if (visible.value === true) {
      closepop()
    } else {
      showpop()
    }
  }
  e.preventDefault();
}
// 获取焦点方法
const getfocus = () => {
  if (prop.trigger === "focus") {
    showpop()
  }
}
// 失去焦点方法
const losefocus = () => {
  if (prop.trigger === "focus") {
    closepop()
  }
}
// 显示
const showpop = () => {
  // 必须先显示，然后才能获取ref，如果反过来，就获取不到ref
  visible.value = true
  nextTick(() => {
    positionContent()
  })
}
// 隐藏
const closepop = () => {
  // 预留100毫秒的时间，100毫秒后，如果鼠标没有放到pop上，就关闭
  let status = false
  if (contentref.value) {
    contentref.value.addEventListener("mouseenter", () => {
      status = true
    })
    contentref.value.addEventListener("mouseleave", () => {
      doClose()
    })
  }
  setTimeout(() => {
    if (!status) {
      visible.value = false
    }
  }, 50)
}
// 立刻隐藏
const doClose = () => {
  visible.value = false
}
// 生命周期
onMounted(() => {
  // 初始化时，根据触发方式，绑定方法
  if (prop.trigger === "hold") {
    popoverref.value.addEventListener("mousedown", showpop)
    popoverref.value.addEventListener("mouseup", closepop)
  } else if (prop.trigger === "hover") {
    popoverref.value.addEventListener("mouseenter", showpop)
    popoverref.value.addEventListener("mouseleave", closepop)
  }
  // 滚动时，不显示pop
  window.addEventListener("scroll", closepop)
  // 窗口大小变化时，不显示pop
  window.addEventListener('resize', closepop)
})
onBeforeUnmount(() => {
  // 销毁前，移除监听
  if (prop.trigger === "hold") {
    popoverref.value.removeEventListener("mousedown", showpop)
    popoverref.value.removeEventListener("mouseup", closepop)
  } else if (prop.trigger === "hover") {
    popoverref.value.removeEventListener("mouseenter", showpop)
    popoverref.value.removeEventListener("mouseleave", closepop)
  }
  // 所有监听移除
  window.removeEventListener("scroll", closepop)
  window.removeEventListener("resize", closepop)
})
// 主动抛出。父组件才能访问到
defineExpose({doClose,showpop})
</script>

<style scoped>

</style>
